/*
 * 文件名： WechatScanPayServiceImpl.java
 * 
 * 工程名称: bis-service
 *
 * Gopay
 *
 * 创建日期： 2016年8月5日
 *
 * Copyright(C) 2016, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.service.bank.impl.scan;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.common.util.constants.BisPayConstants;
import com.gopay.bis.manager.bank.scan.WechatScanPayManager;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.WechatScanConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.wechat.scan.req.ScanOrderQueryReqMsg;
import com.gopay.common.domain.bank.wechat.scan.req.ScanPayReqMsg;
import com.gopay.common.domain.bank.wechat.scan.req.ScanRefundQueryReqMsg;
import com.gopay.common.domain.bank.wechat.scan.req.ScanRefundReqMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanOrderQueryResMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanPayResultMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanPayServerNotifyMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanRefundItem;
import com.gopay.common.domain.bank.wechat.scan.res.ScanRefundQueryResMsg;
import com.gopay.common.domain.bank.wechat.scan.res.ScanRefundResMsg;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.ScanPayInteractRemoteService;

/**
 * 微信扫码支付业务实现
 *
 * @author 宣广海
 *
 * @version
 *
 * @since 2016年8月5日
 */

public class WechatScanPayServiceImpl implements ScanPayInteractRemoteService {
	
	private static Logger logger = LoggerFactory.getLogger(WechatScanPayServiceImpl.class);
	@Resource(name = "wechatScanPayManager")
	private WechatScanPayManager wechatScanPayManager;

	@Override
	public Result pay(BaseMessage msg) throws GopayException {
		Result result = new Result(false);
		try {

			ScanPayReqMsg message = new ScanPayReqMsg();
			BeanUtils.copyProperties(msg, message);
			ScanPayResultMsg resMessage = (ScanPayResultMsg) wechatScanPayManager.sign(message);
			msg.setBankOrderId(message.getBankOrderId());
			if (resMessage != null) {
				if ("0".equals(resMessage.getStatus())) {
					if ("0".equals(resMessage.getResult_code())) {
						resMessage.setCodeUrl(resMessage.getCode_url());
						resMessage.setCodeImage(resMessage.getCode_img_url());
						result.setDefaultModel(resMessage); // 收银台从ScanPayBaseMessage
															// 类获取支付请求结果
						result.setSuccess(true);
					} else {
						result.setResultCode(ProcCodeConstants.PROC_CODE_100E1153);
						result.setErrorMsg(resMessage.getErr_msg());
						result.setSuccess(false);
					}
				} else {
					result.setSuccess(false);
					result.setResultCode(ProcCodeConstants.PROC_CODE_100E1153);
					result.setErrorMsg(resMessage.getMessage());
				}
			} else {
				result.setSuccess(false);
				result.setResultCode(ProcCodeConstants.PROC_CODE_100E7025);
			}
		} catch (GopayException e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E7025);
		}
		return result;
	}

	@SuppressWarnings("unused")
	@Override
	public Result orderQuery(BaseMessage msg) throws GopayException {
		Result result = new Result();
		try {

			ScanOrderQueryReqMsg message = new ScanOrderQueryReqMsg();
			BeanUtils.copyProperties(msg, message);
			ScanOrderQueryResMsg resMsg = (ScanOrderQueryResMsg) wechatScanPayManager.orderQuery(message);
			if (("".equals(resMsg.getTotal_fee())) || (resMsg.getTotal_fee() == null)) {
				resMsg.setAmount(message.getAmount());
			} else {
				resMsg.setAmount(new BigDecimal(resMsg.getTotal_fee()).divide(new BigDecimal(100)));
			}
			result.setDefaultModel(resMsg);
			result.setSuccess(true);
			if (BisPayCheckUtils.checkExternalOrderID(message.getOrderId())) {
				Map<String, String> param = new HashMap<String, String>();
				param.put("orderId", message.getOrderId());
				param.put("amount", message.getAmount().toString());
				if (resMsg == null) {
					// 查询订单为空
					param.put("returnCode", BisPayConstants.QUERYSTATE_FAIL);
					param.put("returnMessage", "银行返回对账结果为空");
					param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
					result.setModel("queryResult", param);
					return result;
				}
				if (StringUtils.isNotBlank(resMsg.getErr_code()) || StringUtils.isNotBlank(resMsg.getErr_msg())) {
					// 订单查询错误
					param.put("returnCode", BisPayConstants.QUERYSTATE_FAIL);
					param.put("returnMessage", resMsg.getErr_msg());
					param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
				}
				if ("0".equals(resMsg.getResult_code()) && StringUtils.isNotBlank(resMsg.getTrade_state())) {
					String tradeState = resMsg.getTrade_state();
					param.put("returnCode", BisPayConstants.QUERYSTATE_SUCCESS);
					if (WechatScanConstants.WECHAT_SCAN_QUERY_SUCCESS.equals(tradeState)) {
						// 支付成功
						param.put("tradeState", BisPayConstants.TRADESTATE_SUCCESS);
						param.put("returnMessage", "交易成功");
					} else if (WechatScanConstants.WECHAT_SCAN_QUERY_CLOSED.equals(tradeState)) {
						param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
						param.put("returnMessage", "已关闭");
					} else if (WechatScanConstants.WECHAT_SCAN_QUERY_REFUND.equals(tradeState)) {
						param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
						param.put("returnMessage", "转入退款");
					} else if (WechatScanConstants.WECHAT_SCAN_QUERY_NOTPAY.equals(tradeState)) {
						param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
						param.put("returnMessage", "未支付");
					} else {
						param.put("tradeState", BisPayConstants.TRADESTATE_FAIL);
						param.put("returnMessage", "支付失败");
					}
				}
			}
		} catch (GopayException e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E7027);
		}
		return result;
	}

	@Override
	public Result refund(BaseMessage msg) throws GopayException {

		Result result = new Result(false);
		try {
			ScanRefundReqMsg message = new ScanRefundReqMsg();
			BeanUtils.copyProperties(msg, message);
			ScanRefundResMsg resMsg = (ScanRefundResMsg) wechatScanPayManager.refund(message);

			if (resMsg != null) {
				if ("0".equals(resMsg.getStatus())) {
					if ("0".equals(resMsg.getResult_code())) {
						result.setDefaultModel(resMsg);
						result.setSuccess(true);
						// 接收成功
						result.setModel("falg", true);
					} else {
						result.setResultCode(ProcCodeConstants.PROC_CODE_100E6088);
						result.setErrorMsg(resMsg.getErr_msg());
						result.setModel("falg", false);
						result.setSuccess(true);
					}
				} else {
					result.setSuccess(false);
					result.setModel("falg", false);
					result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
					result.setErrorMsg(resMsg.getMessage());
				}
			} else {
				result.setSuccess(false);
				result.setModel("falg", false);
				result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
			}

		} catch (GopayException e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(e.getErrCode());
		} catch (Exception e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6087);
		}
		return result;

	}

	@Override
	public Result refundQuery(BaseMessage msg) throws GopayException {
		Result result = new Result(false);
		ScanRefundQueryReqMsg message = new ScanRefundQueryReqMsg();
		BeanUtils.copyProperties(msg, message);
		try {
			ScanRefundQueryResMsg res = (ScanRefundQueryResMsg) wechatScanPayManager.refundQuery(message);
			if ("0".equals(res.getStatus())){
				if ("0".equals(res.getResult_code())){
					int refundCount = res.getRefund_count();
					for (int i = 0; i < refundCount; i++) {
						ScanRefundItem refundItem = res.getRefundItems().get(i);
						if (refundItem.getOut_refund_no().equals(message.getBankOrderId())){
							res.setAmount(new BigDecimal(TransUtil.amountConvert2Yuan(refundItem.getRefund_fee())));
						}
					}
				}
			}
			result.setDefaultModel(res);
			result.setSuccess(true);
		} catch (GopayException e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6033);
		}
		return result;
	}

	@Override
	public Result verify(BaseMessage msg) throws GopayException {
		Result result = new Result(false);
		try {
			ScanPayServerNotifyMsg message = (ScanPayServerNotifyMsg) msg;
			Boolean flag = (Boolean) wechatScanPayManager.verify(message);
			result.setDefaultModel(flag);
			result.setSuccess(true);
			result.setModel("res", message);
			Map<String, String> param = new HashMap<String, String>();
			// 验签成功
			if ((boolean) result.getDefaultModel()) {
				if (("0".equals(message.getPay_result()))) {
					param.put("orderId", message.getOrderId());
					param.put("amt", new BigDecimal(message.getTotal_fee()).divide(new BigDecimal(100)).toString());
					param.put("cardType", "Unknown");
					param.put("notifyNum", "1");
					param.put("payStatus", "00");
					param.put("retCode", "00");
					param.put("retMsg", "验签成功");
					param.put("signData", "");
					param.put("isFront", String.valueOf(message.isFront()));
					result.setModel("isNotifyCashier", param);
					result.setOrderStatus(true);
				} else {
					param.put("orderId", message.getOrderId());
					param.put("amt", new BigDecimal(message.getTotal_fee()).divide(new BigDecimal(100)).toString());
					param.put("cardType", "Unknown");
					param.put("notifyNum", "1");
					param.put("payStatus", "01");
					param.put("retCode", "01");
					param.put("retMsg", "验签失败");
					param.put("signData", "");
					param.put("isFront", String.valueOf(message.isFront()));
					result.setModel("isNotifyCashier", param);
					result.setOrderStatus(false);
				}
			}

		} catch (GopayException e) {
			BankLogUtils.printServiceImplExceptionLog(e);
			result.setResultCode(e.getErrCode());
		} catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6064);
		}
		return result;
	}

}
